From 6636b81573c1048d91cb1c5ac16ab2698d21ee23 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 29 Oct 2022 14:26:39 -0700 Subject: core: hle: kernel: k_handle_table: Refresh. --- src/core/hle/kernel/k_handle_table.cpp | 33 +++++----- src/core/hle/kernel/k_handle_table.h | 108 ++++++++++++++++++++++----------- 2 files changed, 87 insertions(+), 54 deletions(-) diff --git a/src/core/hle/kernel/k_handle_table.cpp b/src/core/hle/kernel/k_handle_table.cpp index e830ca46e..1c7a766c8 100644 --- a/src/core/hle/kernel/k_handle_table.cpp +++ b/src/core/hle/kernel/k_handle_table.cpp @@ -5,14 +5,11 @@ namespace Kernel { -KHandleTable::KHandleTable(KernelCore& kernel_) : kernel{kernel_} {} -KHandleTable::~KHandleTable() = default; - Result KHandleTable::Finalize() { // Get the table and clear our record of it. u16 saved_table_size = 0; { - KScopedDisableDispatch dd(kernel); + KScopedDisableDispatch dd{m_kernel}; KScopedSpinLock lk(m_lock); std::swap(m_table_size, saved_table_size); @@ -25,28 +22,28 @@ Result KHandleTable::Finalize() { } } - return ResultSuccess; + R_SUCCEED(); } bool KHandleTable::Remove(Handle handle) { // Don't allow removal of a pseudo-handle. - if (Svc::IsPseudoHandle(handle)) { + if (Svc::IsPseudoHandle(handle)) [[unlikely]] { return false; } // Handles must not have reserved bits set. const auto handle_pack = HandlePack(handle); - if (handle_pack.reserved != 0) { + if (handle_pack.reserved != 0) [[unlikely]] { return false; } // Find the object and free the entry. KAutoObject* obj = nullptr; { - KScopedDisableDispatch dd(kernel); + KScopedDisableDispatch dd{m_kernel}; KScopedSpinLock lk(m_lock); - if (this->IsValidHandle(handle)) { + if (this->IsValidHandle(handle)) [[likely]] { const auto index = handle_pack.index; obj = m_objects[index]; @@ -57,13 +54,13 @@ bool KHandleTable::Remove(Handle handle) { } // Close the object. - kernel.UnregisterInUseObject(obj); + m_kernel.UnregisterInUseObject(obj); obj->Close(); return true; } Result KHandleTable::Add(Handle* out_handle, KAutoObject* obj) { - KScopedDisableDispatch dd(kernel); + KScopedDisableDispatch dd{m_kernel}; KScopedSpinLock lk(m_lock); // Never exceed our capacity. @@ -82,22 +79,22 @@ Result KHandleTable::Add(Handle* out_handle, KAutoObject* obj) { *out_handle = EncodeHandle(static_cast(index), linear_id); } - return ResultSuccess; + R_SUCCEED(); } Result KHandleTable::Reserve(Handle* out_handle) { - KScopedDisableDispatch dd(kernel); + KScopedDisableDispatch dd{m_kernel}; KScopedSpinLock lk(m_lock); // Never exceed our capacity. R_UNLESS(m_count < m_table_size, ResultOutOfHandles); *out_handle = EncodeHandle(static_cast(this->AllocateEntry()), this->AllocateLinearId()); - return ResultSuccess; + R_SUCCEED(); } void KHandleTable::Unreserve(Handle handle) { - KScopedDisableDispatch dd(kernel); + KScopedDisableDispatch dd{m_kernel}; KScopedSpinLock lk(m_lock); // Unpack the handle. @@ -108,7 +105,7 @@ void KHandleTable::Unreserve(Handle handle) { ASSERT(reserved == 0); ASSERT(linear_id != 0); - if (index < m_table_size) { + if (index < m_table_size) [[likely]] { // NOTE: This code does not check the linear id. ASSERT(m_objects[index] == nullptr); this->FreeEntry(index); @@ -116,7 +113,7 @@ void KHandleTable::Unreserve(Handle handle) { } void KHandleTable::Register(Handle handle, KAutoObject* obj) { - KScopedDisableDispatch dd(kernel); + KScopedDisableDispatch dd{m_kernel}; KScopedSpinLock lk(m_lock); // Unpack the handle. @@ -127,7 +124,7 @@ void KHandleTable::Register(Handle handle, KAutoObject* obj) { ASSERT(reserved == 0); ASSERT(linear_id != 0); - if (index < m_table_size) { + if (index < m_table_size) [[likely]] { // Set the entry. ASSERT(m_objects[index] == nullptr); diff --git a/src/core/hle/kernel/k_handle_table.h b/src/core/hle/kernel/k_handle_table.h index 0864a737c..e98a01c86 100644 --- a/src/core/hle/kernel/k_handle_table.h +++ b/src/core/hle/kernel/k_handle_table.h @@ -21,33 +21,38 @@ namespace Kernel { class KernelCore; class KHandleTable { -public: YUZU_NON_COPYABLE(KHandleTable); YUZU_NON_MOVEABLE(KHandleTable); +public: static constexpr size_t MaxTableSize = 1024; - explicit KHandleTable(KernelCore& kernel_); - ~KHandleTable(); +public: + explicit KHandleTable(KernelCore& kernel) : m_kernel(kernel) {} Result Initialize(s32 size) { + // Check that the table size is valid. R_UNLESS(size <= static_cast(MaxTableSize), ResultOutOfMemory); + // Lock. + KScopedDisableDispatch dd{m_kernel}; + KScopedSpinLock lk(m_lock); + // Initialize all fields. m_max_count = 0; - m_table_size = static_cast((size <= 0) ? MaxTableSize : size); + m_table_size = static_cast((size <= 0) ? MaxTableSize : size); m_next_linear_id = MinLinearId; m_count = 0; m_free_head_index = -1; // Free all entries. - for (s16 i = 0; i < static_cast(m_table_size); ++i) { + for (s32 i = 0; i < static_cast(m_table_size); ++i) { m_objects[i] = nullptr; - m_entry_infos[i].next_free_index = i - 1; + m_entry_infos[i].next_free_index = static_cast(i - 1); m_free_head_index = i; } - return ResultSuccess; + R_SUCCEED(); } size_t GetTableSize() const { @@ -66,13 +71,13 @@ public: template KScopedAutoObject GetObjectWithoutPseudoHandle(Handle handle) const { // Lock and look up in table. - KScopedDisableDispatch dd(kernel); + KScopedDisableDispatch dd{m_kernel}; KScopedSpinLock lk(m_lock); - if constexpr (std::is_same_v) { + if constexpr (std::is_same::value) { return this->GetObjectImpl(handle); } else { - if (auto* obj = this->GetObjectImpl(handle); obj != nullptr) { + if (auto* obj = this->GetObjectImpl(handle); obj != nullptr) [[likely]] { return obj->DynamicCast(); } else { return nullptr; @@ -85,13 +90,13 @@ public: // Handle pseudo-handles. if constexpr (std::derived_from) { if (handle == Svc::PseudoHandle::CurrentProcess) { - auto* const cur_process = kernel.CurrentProcess(); + auto* const cur_process = m_kernel.CurrentProcess(); ASSERT(cur_process != nullptr); return cur_process; } } else if constexpr (std::derived_from) { if (handle == Svc::PseudoHandle::CurrentThread) { - auto* const cur_thread = GetCurrentThreadPointer(kernel); + auto* const cur_thread = GetCurrentThreadPointer(m_kernel); ASSERT(cur_thread != nullptr); return cur_thread; } @@ -100,6 +105,37 @@ public: return this->template GetObjectWithoutPseudoHandle(handle); } + KScopedAutoObject GetObjectForIpcWithoutPseudoHandle(Handle handle) const { + // Lock and look up in table. + KScopedDisableDispatch dd{m_kernel}; + KScopedSpinLock lk(m_lock); + + return this->GetObjectImpl(handle); + } + + KScopedAutoObject GetObjectForIpc(Handle handle, KThread* cur_thread) const { + // Handle pseudo-handles. + ASSERT(cur_thread != nullptr); + if (handle == Svc::PseudoHandle::CurrentProcess) { + auto* const cur_process = + static_cast(static_cast(cur_thread->GetOwnerProcess())); + ASSERT(cur_process != nullptr); + return cur_process; + } + if (handle == Svc::PseudoHandle::CurrentThread) { + return static_cast(cur_thread); + } + + return GetObjectForIpcWithoutPseudoHandle(handle); + } + + KScopedAutoObject GetObjectByIndex(Handle* out_handle, size_t index) const { + KScopedDisableDispatch dd{m_kernel}; + KScopedSpinLock lk(m_lock); + + return this->GetObjectByIndexImpl(out_handle, index); + } + Result Reserve(Handle* out_handle); void Unreserve(Handle handle); @@ -112,7 +148,7 @@ public: size_t num_opened; { // Lock the table. - KScopedDisableDispatch dd(kernel); + KScopedDisableDispatch dd{m_kernel}; KScopedSpinLock lk(m_lock); for (num_opened = 0; num_opened < num_handles; num_opened++) { // Get the current handle. @@ -120,13 +156,13 @@ public: // Get the object for the current handle. KAutoObject* cur_object = this->GetObjectImpl(cur_handle); - if (cur_object == nullptr) { + if (cur_object == nullptr) [[unlikely]] { break; } // Cast the current object to the desired type. T* cur_t = cur_object->DynamicCast(); - if (cur_t == nullptr) { + if (cur_t == nullptr) [[unlikely]] { break; } @@ -137,7 +173,7 @@ public: } // If we converted every object, succeed. - if (num_opened == num_handles) { + if (num_opened == num_handles) [[likely]] { return true; } @@ -191,21 +227,21 @@ private: ASSERT(reserved == 0); // Validate our indexing information. - if (raw_value == 0) { + if (raw_value == 0) [[unlikely]] { return false; } - if (linear_id == 0) { + if (linear_id == 0) [[unlikely]] { return false; } - if (index >= m_table_size) { + if (index >= m_table_size) [[unlikely]] { return false; } // Check that there's an object, and our serial id is correct. - if (m_objects[index] == nullptr) { + if (m_objects[index] == nullptr) [[unlikely]] { return false; } - if (m_entry_infos[index].GetLinearId() != linear_id) { + if (m_entry_infos[index].GetLinearId() != linear_id) [[unlikely]] { return false; } @@ -215,11 +251,11 @@ private: KAutoObject* GetObjectImpl(Handle handle) const { // Handles must not have reserved bits set. const auto handle_pack = HandlePack(handle); - if (handle_pack.reserved != 0) { + if (handle_pack.reserved != 0) [[unlikely]] { return nullptr; } - if (this->IsValidHandle(handle)) { + if (this->IsValidHandle(handle)) [[likely]] { return m_objects[handle_pack.index]; } else { return nullptr; @@ -227,9 +263,8 @@ private: } KAutoObject* GetObjectByIndexImpl(Handle* out_handle, size_t index) const { - // Index must be in bounds. - if (index >= m_table_size) { + if (index >= m_table_size) [[unlikely]] { return nullptr; } @@ -244,18 +279,15 @@ private: private: union HandlePack { - HandlePack() = default; - HandlePack(Handle handle) : raw{static_cast(handle)} {} + constexpr HandlePack() = default; + constexpr HandlePack(Handle handle) : raw{static_cast(handle)} {} - u32 raw; + u32 raw{}; BitField<0, 15, u32> index; BitField<15, 15, u32> linear_id; BitField<30, 2, u32> reserved; }; - static constexpr u16 MinLinearId = 1; - static constexpr u16 MaxLinearId = 0x7FFF; - static constexpr Handle EncodeHandle(u16 index, u16 linear_id) { HandlePack handle{}; handle.index.Assign(index); @@ -264,6 +296,10 @@ private: return handle.raw; } +private: + static constexpr u16 MinLinearId = 1; + static constexpr u16 MaxLinearId = 0x7FFF; + union EntryInfo { u16 linear_id; s16 next_free_index; @@ -271,21 +307,21 @@ private: constexpr u16 GetLinearId() const { return linear_id; } - constexpr s16 GetNextFreeIndex() const { + constexpr s32 GetNextFreeIndex() const { return next_free_index; } }; private: + KernelCore& m_kernel; std::array m_entry_infos{}; std::array m_objects{}; - s32 m_free_head_index{-1}; + mutable KSpinLock m_lock; + s32 m_free_head_index{}; u16 m_table_size{}; u16 m_max_count{}; - u16 m_next_linear_id{MinLinearId}; + u16 m_next_linear_id{}; u16 m_count{}; - mutable KSpinLock m_lock; - KernelCore& kernel; }; } // namespace Kernel -- cgit v1.2.3